using System;
using System.Collections.Generic;
using System.Text;

namespace RapidHDL
{
    public class TestPCSDRAM : RapidHardware
    {
        PipelineSerialAssembler oAssembler;
        public override bool ConfigureSettings()
        {
            Settings.UseStart = false;
            Settings.BuildHardware = true;
            Settings.ForceBuildHardware = false;
            Settings.RunFromXilinx = true;
            Settings.ClockFrequency = 10;
            Settings.UseSDRAM = true;
            Settings.BuildRemote = false;
            return true;
        }

        public override bool GenerateStructure(TopLevelComponent TopLevelComponent)
        {
            // why required?
            TopLevelComponent.SDRAMInterface.Enabled = true;
            TopLevelComponent.FIFOInterface.Enabled = true;
            TopLevelComponent.TestBusWrite.Join(0);


            PipelineBuffer oInBuffer = new PipelineBuffer(TopLevelComponent, "in_buffer", TopLevelComponent.MainClock, TopLevelComponent.MainReset, 18, 4);
            PipelineBuffer oOutBuffer = new PipelineBuffer(TopLevelComponent, "out_buffer", TopLevelComponent.MainClock, TopLevelComponent.MainReset, 16, 4);
            PipelineBuffer oDataBuffer = new PipelineBuffer(TopLevelComponent, "data_buffer", TopLevelComponent.MainClock, TopLevelComponent.MainReset, 64, 4);

            PipelineStage oIsolationBuffer = new PipelineStage(TopLevelComponent, "isolation_buffer", TopLevelComponent.MainClock, TopLevelComponent.MainReset, 64);

            oInBuffer.InputBus.Join(TopLevelComponent.FIFOInterface.BusFromExternal);
            oAssembler = new PipelineSerialAssembler(TopLevelComponent, "assembler", TopLevelComponent.MainClock, TopLevelComponent.MainReset, 18, 16, 2, 4);
            oAssembler.InputBus.Join(oInBuffer.OutputBus);
            oAssembler.OutputBus.Join(oIsolationBuffer.InputBus);

            oIsolationBuffer.OutputBus.Join(TopLevelComponent.SDRAMInterface.BusFromInternal);

            PipelineStage oIsolationBuffer2 = new PipelineStage(TopLevelComponent, "isolation_buffer2", TopLevelComponent.MainClock, TopLevelComponent.MainReset, 42);
            oIsolationBuffer2.InputBus.Join(TopLevelComponent.SDRAMInterface.BusFromExternal);

            PipelineBuffer oSDRAMBuffer = new PipelineBuffer(TopLevelComponent, "sdram_buffer", TopLevelComponent.MainClock, TopLevelComponent.MainReset, 42, 4);
            oSDRAMBuffer.InputBus.Join(oIsolationBuffer2.OutputBus);

            PipelineSerializer oSerializer = new PipelineSerializer(TopLevelComponent, "serializer", TopLevelComponent.MainClock, TopLevelComponent.MainReset,42,14);
            oSerializer.InputBus.Join(oSDRAMBuffer.OutputBus);
            oSerializer.OutputBus.Join(TopLevelComponent.FIFOInterface.BusFromInternal);
            oSerializer.OffsetAddress = true;

            return true;
        }

        public override bool ConfigureSignalViews(TopLevelComponent TopLevelComponent)
        {
            //SystemInterface.AddSignalView("fifo_status", "fifo_ifc.i_status_reg");
            //SystemInterface.AddSignalView("fifo_in", "fifo_ifc.i_fifo_data");

            //SystemInterface.AddSignalView("fifo_in", poTopLevelComponent.FIFOInterface.InputFIFOData,0,14,true);
            //SystemInterface.AddSignalView("fifo_seq", poTopLevelComponent.FIFOInterface.InputFIFOData, 16, 17,true);
            //SystemInterface.AddSignalView("fifo_status", poTopLevelComponent.FIFOInterface.InputStatusReg);
            //SystemInterface.AddSignalView("test", poTopLevelComponent.FIFOInterface.Test);

            SystemInterface.AddSignalView("pipe_data_in", TopLevelComponent.FIFOInterface.BusFromExternal.Data);
            SystemInterface.AddSignalView("pipe_data_in_ready", TopLevelComponent.FIFOInterface.BusFromExternal.DataReady);
            SystemInterface.AddSignalView("pipe_data_out_stall", TopLevelComponent.FIFOInterface.BusFromInternal.Stall);

            SystemInterface.AddSignalView("pipe_data_out", TopLevelComponent.FIFOInterface.BusFromInternal.Data);
            SystemInterface.AddSignalView("pipe_data_out_ready", TopLevelComponent.FIFOInterface.BusFromInternal.DataReady);
            SystemInterface.AddSignalView("pipe_data_in_stall", TopLevelComponent.FIFOInterface.BusFromExternal.Stall);

            SystemInterface.AddSignalView("sdram_out", TopLevelComponent.SDRAMInterface.BusFromExternal.Data);
            SystemInterface.AddSignalView("sdram_ready", TopLevelComponent.SDRAMInterface.BusFromExternal.DataReady);
            SystemInterface.AddSignalView("sdram_stall", TopLevelComponent.SDRAMInterface.BusFromExternal.Stall);

            /*SystemInterface.AddSignalView("state_reset", oAssembler.oStateMachine.StateCurrent("state_reset"));
            SystemInterface.AddSignalView("state_0", oAssembler.oStateMachine.StateCurrent("state_0"));
            SystemInterface.AddSignalView("state_1", oAssembler.oStateMachine.StateCurrent("state_1"));
            SystemInterface.AddSignalView("state_2", oAssembler.oStateMachine.StateCurrent("state_2"));
            SystemInterface.AddSignalView("state_final", oAssembler.oStateMachine.StateCurrent("state_final"));
            SystemInterface.AddSignalView("address", oAssembler.nvAddress);*/

            return true;
        }

        public void ShowFIFO(HardwareScript poScript, int piTime)
        {
            poScript.Echo(piTime,"======================================= Time" + piTime.ToString());
            poScript.SignalView(piTime, "pipe_data_in");
            poScript.SignalView(piTime, "pipe_data_in_ready");
            poScript.Echo(piTime, "--");
            poScript.SignalView(piTime, "pipe_data_out");
            poScript.SignalView(piTime, "pipe_data_out_ready");
            poScript.Echo(piTime, "...");
            poScript.SignalView(piTime, "sdram_out");
            poScript.SignalView(piTime, "sdram_ready");
            poScript.SignalView(piTime, "sdram_stall");
            poScript.SignalView(piTime, ".TEST_BUS_READ_I",SignalFormat.Binary);

            /*poScript.SignalView(piTime, "address");            
            poScript.SignalView(piTime, "state_reset");
            poScript.SignalView(piTime, "state_0");
            poScript.SignalView(piTime, "state_1");
            poScript.SignalView(piTime, "state_2");
            poScript.SignalView(piTime, "state_final");*/
        }

        public override bool GenerateHardwareScripts()
        {
            HardwareScript oScript = HardwareScripts.NewScript("test");
            oScript.NoReset = true;

            for (int iTime = 0; iTime < 30; iTime++)
                ShowFIFO(oScript, iTime);
            return true;
        }

        public static void PCTest()
        {
            const int BLOCKS = 4;

            MemoryBlock oMemoryBlock = new MemoryBlock();

            for (int iX = 0; iX < BLOCKS; iX++)
                oMemoryBlock.WriteMemory(iX + 16, (uint)iX+16); //(uint)iX + 65530);

            IOInterface.PostMemory(ref oMemoryBlock);
            if (!oMemoryBlock.IsReady)
            {
                System.Windows.Forms.MessageBox.Show("Failed Writing \n" + oMemoryBlock.DebugDisplay());
                return;
            }

            oMemoryBlock.Reset();
            for (int iX = 0; iX < BLOCKS; iX++)
                oMemoryBlock.RequestMemory(iX + 16);

            IOInterface.PostMemory(ref oMemoryBlock);
            if (!oMemoryBlock.IsReady)
            {
                System.Windows.Forms.MessageBox.Show("Failed Reading \n" + oMemoryBlock.DebugDisplay());
                return;
            }

            oMemoryBlock.Reset();

            const int cMemStart = 2097151;

            for (int iX = 0; iX < BLOCKS; iX++)
                oMemoryBlock.WriteMemory(iX + cMemStart, (uint)iX);

            IOInterface.PostMemory(ref oMemoryBlock);
            if (!oMemoryBlock.IsReady)
            {
                System.Windows.Forms.MessageBox.Show("Failed Writing Second Block \n" + oMemoryBlock.DebugDisplay());
                return;
            }


            oMemoryBlock.Reset();
            oMemoryBlock.RequestMemory(16);
            oMemoryBlock.RequestMemory(0);
            oMemoryBlock.RequestMemory(2);
            oMemoryBlock.RequestMemory(cMemStart);
            oMemoryBlock.RequestMemory(cMemStart + 2);

            IOInterface.PostMemory(ref oMemoryBlock);
            if (!oMemoryBlock.IsReady)
            {
                System.Windows.Forms.MessageBox.Show("Failed Reading Second Block \n" + oMemoryBlock.DebugDisplay());
                return;
            }



            System.Windows.Forms.MessageBox.Show(oMemoryBlock.DebugDisplay());
        }
    }
}


